module POrd where

import Data.Set
import Data.List


class Eq a => POrd a where
    pcmp :: a -> a -> Maybe Ordering
    ple  :: a -> a -> Bool
    plt  :: a -> a -> Bool
    pge  :: a -> a -> Bool
    pgt  :: a -> a -> Bool

    pcmp x y | x == y    = Just EQ
             | x `ple` y = Just LT
             | y `ple` x = Just GT
             | otherwise = Nothing

    x `ple` y = let r = x `pcmp` y in r == Just LT || r == Just EQ
    x `plt` y = x `pcmp` y == Just LT
    x `pge` y = let r = x `pcmp` y in r == Just GT || r == Just EQ
    x `pgt` y = x `pcmp` y == Just GT

    -- Minimum complete definition: ple or pcmp.

    -- Laws for ple:
    -- Reflexivity:  x `ple` x
    -- Antisymmetry: x `ple` y and y `ple` x ==> x == y
    -- Transitivity: x `ple` y and y `ple` z ==> x `ple` z


instance Ord a => POrd (Set a) where
    ple = isSubsetOf

instance (POrd a) => POrd (Maybe a) where
    Nothing `ple` x         = True
    (Just x) `ple` (Just y) = x `ple` y
    _ `ple` _               = False

instance (POrd a) => POrd [a] where
    ple = isPrefixOf

